/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 bitmap_layer.h

	$Header: /resource_editor/bitmap_layer.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined(BITMAP_LAYER_H_INCLUDED)
#define BITMAP_LAYER_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <string>
#include <vector>
#include "abstract_bitmap.h"
#include "counted_ptr.h"
#include "pixel_24.h"
#include "screen_point.h"
#include "shared_ptr.h"
#include "sized_int_types.h"

class t_progress_handler;
// --------------------------------------------------------
// bitmap layers
// --------------------------------------------------------
struct t_bitmap_row
{
    t_uint16				left;
    t_uint16				right;
    t_uint32				offset;

    int  get_width() const;
};

struct t_bitmap_line // used for Copy operations
{
	int left;
	int right;
};

typedef std::vector<t_bitmap_line> t_bitmap_line_array;

inline int t_bitmap_row::get_width() const
{
    return right - left;
}

// --------------------------------------------------------
// base class for bitmap layers
// --------------------------------------------------------
class t_bitmap_layer 
{
public:   
	virtual ~t_bitmap_layer();

	virtual t_bitmap_layer* adjust_brightness( int brightness ) const = 0;
	virtual t_bitmap_layer* adjust_color( int target_hue, int hue_change, int saturation,
		                                  int brightness ) const = 0;
	virtual t_bitmap_layer* adjust_saturation( int saturation ) const = 0;
	bool                    contains( t_screen_point point ) const; // returns true if pixel
	                                                                // specified by point has
	                                                                // alpha > 0
	virtual t_bitmap_layer* copy( t_screen_point const& origin,
		                          t_bitmap_line_array const& shape ) const = 0;
    void				    draw_to( t_screen_rect source_rect, t_abstract_bitmap16& dest,
                                     t_screen_point dest_point ) const;
	void				    draw_to( t_abstract_bitmap16& dest, t_screen_point dest_point ) const;
    void				    draw_to( t_screen_rect source_rect, t_abstract_bitmap16& dest ) const;
    void				    draw_to( t_abstract_bitmap16& dest ) const;
	// draw with alpha blending
    void				    draw_to( t_screen_rect source_rect, t_abstract_bitmap16& dest,
								     t_screen_point dest_point, int alpha ) const;
	void				    draw_to( t_abstract_bitmap16& dest, t_screen_point dest_point,
		                             int alpha ) const;
	void				    draw_to( t_screen_rect source_rect, t_abstract_bitmap16& dest, 
		                             int alpha ) const;
	void				    draw_to( t_abstract_bitmap16& dest, int alpha ) const;

    int                     get_alpha_depth() const;
	t_uint8*                get_alpha_mask() const;
	int                     get_data_size() const;
    int						get_height() const;
    std::string const &		get_name() const;
    t_screen_rect			get_rect() const;
	t_bitmap_row const*		get_row( int row ) const;
    int						get_width() const;
	virtual void			set_block_alpha();
	void					set_name( std::string const & new_name );
	void					offset( t_screen_point point ); // move rectangle for bitmap
protected:
	virtual bool data_contains( int index ) const = 0;
    virtual void draw( t_screen_rect source_rect, t_abstract_bitmap16& dest,
                       t_screen_point dest_point ) const = 0;
    virtual void draw( t_screen_rect source_rect, t_abstract_bitmap16& dest,
                       t_screen_point dest_point, int alpha ) const = 0;

    std::string                  m_name;
    int                          m_alpha_depth; // 0 = no alpha, 1 = 1 bit, 4 = bit.
    t_screen_rect                m_rect;
    t_shared_array<t_bitmap_row> m_rows;
    t_shared_array<t_uint8>      m_alpha_mask;
	t_shared_array<t_uint8>		 m_block_alpha; // information about alpha values in block
};

// --------------------------------------------------------
// inlines for bitmap layer base
// --------------------------------------------------------
inline int t_bitmap_layer::get_alpha_depth() const
{
    return m_alpha_depth;
}

inline t_uint8* t_bitmap_layer::get_alpha_mask() const
{
	return m_alpha_mask.get();
}

inline int t_bitmap_layer::get_height() const
{
    return m_rect.height();
}

inline std::string const & t_bitmap_layer::get_name() const
{
    return m_name;
}

inline t_screen_rect t_bitmap_layer::get_rect() const
{
    return m_rect;
}

inline t_bitmap_row const* t_bitmap_layer::get_row( int row ) const
{
	return m_rows.get() + row;
}

inline int t_bitmap_layer::get_width() const
{
    return m_rect.width();
}

inline void t_bitmap_layer::offset( t_screen_point point )
{
	m_rect += point;
}

inline void t_bitmap_layer::set_name( std::string const & new_name )
{
	m_name = new_name;
}

inline void	t_bitmap_layer::draw_to( t_screen_rect source_rect, t_abstract_bitmap16& dest,
                                          t_screen_point dest_point ) const
{
	draw( source_rect, dest, dest_point );
}

inline void t_bitmap_layer::draw_to( t_abstract_bitmap16& dest, t_screen_point dest_point ) const
{
    draw( m_rect, dest, dest_point + m_rect.top_left() );
}

inline void t_bitmap_layer::draw_to( t_screen_rect source_rect, t_abstract_bitmap16& dest ) const
{
    draw( source_rect, dest, t_screen_point(0,0) );
}

inline void t_bitmap_layer::draw_to( t_abstract_bitmap16& dest ) const
{
    draw( m_rect, dest, m_rect.top_left() );
}

inline void t_bitmap_layer::draw_to( t_screen_rect source_rect, t_abstract_bitmap16& dest,
                                          t_screen_point dest_point, int alpha ) const
{
	if (alpha == 0)
		return;
	if (alpha == 15)
		draw( source_rect, dest, dest_point );
	else
		draw( source_rect, dest, dest_point, alpha );
}

inline void t_bitmap_layer::draw_to( t_abstract_bitmap16& dest, t_screen_point dest_point,
									 int alpha ) const
{
    draw_to( m_rect, dest, dest_point + m_rect.top_left(), alpha );
}

inline void t_bitmap_layer::draw_to( t_screen_rect source_rect, t_abstract_bitmap16& dest,
									 int alpha ) const
{
    draw_to( source_rect, dest, t_screen_point(0,0), alpha );
}

inline void t_bitmap_layer::draw_to( t_abstract_bitmap16& dest, int alpha ) const
{
    draw_to( m_rect, dest, m_rect.top_left(), alpha );
}

// --------------------------------------------------------
// 16 bit bitmap layer
// --------------------------------------------------------
class t_bitmap_layer_16 : public t_bitmap_layer
{
public:
	t_bitmap_layer_16( std::string const& name, t_screen_rect const& rect, int alpha_depth, 
		               t_bitmap_row const* const rows, 
			           t_shared_array<t_uint16>& data, t_shared_array<t_uint8>& alpha_mask );

	virtual t_bitmap_layer* adjust_brightness( int brightness ) const;
	virtual t_bitmap_layer* adjust_color( int target_hue, int hue_change, int saturation,
		                                  int brightness ) const;
	virtual t_bitmap_layer* adjust_saturation( int saturation ) const;
	virtual t_bitmap_layer* copy( t_screen_point const& origin,
		                          t_bitmap_line_array const& shape ) const;
	t_uint16*			   get_data() const;
protected:
	virtual bool data_contains( int index ) const;
    virtual void draw( t_screen_rect source_rect, t_abstract_bitmap16& dest,
                       t_screen_point dest_point ) const;
    virtual void draw( t_screen_rect source_rect, t_abstract_bitmap16& dest,
                       t_screen_point dest_point, int alpha ) const;

	t_shared_array<t_uint16> m_data;
};

inline t_uint16* t_bitmap_layer_16::get_data() const
{
	return m_data.get();
}

// --------------------------------------------------------
// paletted bitmap layer
// --------------------------------------------------------
class t_paletted_layer : public t_bitmap_layer
{
public:  
	t_uint8*                get_data() const;
protected:
	virtual bool data_contains( int index ) const;

    t_shared_array<t_uint8>      m_data;
};

inline t_uint8* t_paletted_layer::get_data() const
{
	return m_data.get();
}

// --------------------------------------------------------
// 24 bit paletted bitmap layer
// --------------------------------------------------------
class t_bitmap_layer_24 : public t_paletted_layer
{
public:
    std::vector<t_pixel_24> const& get_palette() const;
 
	virtual t_bitmap_layer* adjust_brightness( int brightness ) const;
	virtual t_bitmap_layer* adjust_color( int target_hue, int hue_change, int saturation,
		                                  int brightness ) const;
	virtual t_bitmap_layer* adjust_saturation( int saturation ) const;
	virtual t_bitmap_layer* copy( t_screen_point const& origin,
		                          t_bitmap_line_array const& shape ) const;
	void init( std::string const& name, t_screen_rect const& rect, int alpha_depth, 
		       std::vector<t_pixel_24> const& palette, t_bitmap_row const* const rows, 
			   t_uint8 const* const data, t_uint8 const* const alpha_mask );
	void init( std::string const& name, t_screen_rect const& rect, int alpha_depth, 
		       std::vector<t_pixel_24> const& palette, t_bitmap_row const* const rows, 
			   t_shared_array<t_uint8>& data, t_shared_array<t_uint8>& alpha_mask );
    bool read( std::streambuf& buffer );
    bool read( std::streambuf& buffer, t_progress_handler* handler );
    bool write( std::streambuf& buffer ) const;
protected:
    virtual void draw( t_screen_rect source_rect, t_abstract_bitmap16& dest,
                       t_screen_point dest_point ) const;
    virtual void draw( t_screen_rect source_rect, t_abstract_bitmap16& dest,
                       t_screen_point dest_point, int alpha ) const;

    std::vector<t_pixel_24> m_palette;
};

inline std::vector<t_pixel_24> const& t_bitmap_layer_24::get_palette() const
{
	return m_palette;
}

inline bool t_bitmap_layer_24::read( std::streambuf& buffer )
{
	return read( buffer, 0 );
}

// --------------------------------------------------------
// 16 bit paletted bitmap layer
// --------------------------------------------------------
class t_paletted_16_layer : public t_paletted_layer
{
public:
    explicit t_paletted_16_layer( t_bitmap_layer_24 const& source );
	t_paletted_16_layer( std::string const& name, t_screen_rect const& rect, 
				 		 int alpha_depth, std::vector<t_uint16> const& palette, 
		                 t_bitmap_row const* const rows, 
			             t_shared_array<t_uint8>& data, t_shared_array<t_uint8>& alpha_mask );

	virtual t_bitmap_layer* adjust_brightness( int brightness ) const;
	virtual t_bitmap_layer* adjust_color( int target_hue, int hue_change, int saturation,
		                                  int brightness ) const;
	virtual t_bitmap_layer* adjust_saturation( int saturation ) const;
	virtual t_bitmap_layer* copy( t_screen_point const& origin,
		                          t_bitmap_line_array const& shape ) const;
protected:
    virtual void draw( t_screen_rect source_rect, t_abstract_bitmap16& dest,
                       t_screen_point dest_point ) const;
    virtual void draw( t_screen_rect source_rect, t_abstract_bitmap16& dest,
                       t_screen_point dest_point, int alpha ) const;
    std::vector<t_uint16> m_palette;
};



#endif // BITMAP_LAYER_H_INCLUDED